package com.star.markdown;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.*;
import java.net.URI;
import java.net.URL;

public class MarkdownUtils {
    private static Markdown markdown = new Markdown();

    public MarkdownUtils() {
    }

    /**
     * 将文件转成 HTML 文件，存放在当前文件夹中
     *
     * @param markdownPath /
     * @throws IOException /
     */
    public static void toHtml(String markdownPath) throws IOException {
        toHtml(new File(markdownPath), new File(markdownPath.replace(".md", ".html")));
    }

    /**
     * 将文件转成 HTML 文件
     *
     * @param markdownPath /
     * @param toHtmlPath   /
     * @throws IOException /
     */
    public static void toHtml(String markdownPath, String toHtmlPath) throws IOException {
        toHtml(new File(markdownPath), new File(toHtmlPath));
    }

    /**
     * 将文件转成 HTML 文件
     *
     * @param markdownFile /
     * @param toHtmlFile   /
     * @throws IOException /
     */
    public static void toHtml(File markdownFile, File toHtmlFile) throws IOException {
        String name = toHtmlFile.getName();
        String title = name.replaceAll(".html", "");
        OutputStream toHtmlStream = new FileOutputStream(toHtmlFile);
        InputStream markdownStream = new FileInputStream(markdownFile);
        ByteArrayOutputStream baos = null;
        BufferedWriter writer = null;

        try {
            baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];

            int len;
            while ((len = markdownStream.read(buffer)) != -1) {
                baos.write(buffer, 0, len);
            }

            String bodyHtml = markdown.parse(baos.toString());
            String body = convertBody(markdownFile.getParentFile(), bodyHtml);
            String html = mergeTemplate(title, body);
            writer = new BufferedWriter(new OutputStreamWriter(toHtmlStream));
            writer.write(html);
        } finally {
            closeio(markdownStream);
            closeio(baos);
            closeio(writer);
            closeio(toHtmlStream);
        }
    }

    /**
     * 将 html body中的图片转成 base64  编码
     *
     * @param parent /
     * @param bodyHtml /
     * @return /
     */
    private static String convertBody(File parent, String bodyHtml) {
        Document doc = Jsoup.parse(bodyHtml);
        Elements imgs = doc.select("img[src]");
        if (imgs != null) {
            for (Element element : imgs) {
                String src = element.attr("src");
                String path = parent.getAbsolutePath();
                try {
                    String image = toBase64Image(path + "\\" + src);
                    element.attr("src", "data:image/jpg;base64," + image);
                } catch (IOException var7) {
                    var7.printStackTrace();
                }
            }
        }

        return doc.toString();
    }

    /**
     * 将 html body中的图片转成 base64  编码
     *
     * @param bodyHtml /
     * @return /
     */
    private static String convertBody(String bodyHtml) {
        Document doc = Jsoup.parse(bodyHtml);
        Elements imgs = doc.select("img[src]");
        if (imgs != null) {
            for (Element element : imgs) {
                String src = element.attr("src");
                try {
                    String image = toBase64Image(src);
                    element.attr("src", "data:image/jpg;base64," + image);
                } catch (IOException var7) {
                    var7.printStackTrace();
                }
            }
        }

        return doc.toString();
    }

    /**
     * 将图片转成 base64  编码
     *
     * @param src /
     * @return /
     * @throws IOException /
     */
    private static String toBase64Image(String src) throws IOException {
        FileInputStream fis = null;
        ByteArrayOutputStream baos = null;

        try {
            String file = src;
            if (src.startsWith("file:")) {
                URI uri = URI.create(src);
                URL url = uri.toURL();
                file = url.getFile();
            }

            baos = new ByteArrayOutputStream();
            fis = new FileInputStream(file);
            byte[] buffer = new byte[1024];

            int len;
            while ((len = fis.read(buffer)) != -1) {
                baos.write(buffer, 0, len);
            }

            byte[] data = baos.toByteArray();
            return new String(Base64.encodeBase64(data));
        } finally {
            closeio(fis);
            closeio(baos);
        }
    }

    /**
     * 生成 模板
     *
     * @param title /
     * @param body  /
     * @return /
     */
    private static String mergeTemplate(String title, String body) {
        VelocityEngine ve = new VelocityEngine();
        ve.setProperty("resource.loader", "classpath");
        ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
        ve.setProperty("ISO-8859-1", "utf-8");
        ve.setProperty("input.encoding", "utf-8");
        ve.setProperty("output.encoding", "utf-8");
        ve.init();
        Template template = ve.getTemplate("markdown/vm/html.vm");
        VelocityContext ctx = new VelocityContext();

        // ----------------------------------------------------------------------------------------
        // 页面标题
        ctx.put("title", title);
        try {
            ctx.put("markdownCSS", readJsOrcss("/markdown/css/github-markdown-old.css"));
            ctx.put("jqueryZtreeTocCSS", readJsOrcss("/markdown/css/zTreeStyle.css"));
            ctx.put("highlightCSS", readJsOrcss("/markdown/css/highlight.css"));

            ctx.put("jquery", readJsOrcss("/markdown/js/jquery-1.4.4.min.js"));
            ctx.put("jqueryZtree", readJsOrcss("/markdown/js/jquery.ztree.all-3.5.min.js"));
            ctx.put("jqueryZtreeToc", readJsOrcss("/markdown/js/ztree_toc.min.js"));
            ctx.put("highlight", readJsOrcss("/markdown/js/highlight.min.js"));
            ctx.put("highlightNumbers", readJsOrcss("/markdown/js/highlightjs-line-numbers.min.js"));
        } catch (IOException var6) {
            var6.printStackTrace();
        }
        // 页面  body 内容
        ctx.put("body", body);
        // ----------------------------------------------------------------------------------------

        StringWriter sw = new StringWriter();
        // 生成模板
        template.merge(ctx, sw);
        return sw.toString();
    }

    /**
     * 读取 js 或者 css 文件
     *
     * @param src /
     * @return /
     * @throws IOException /
     */
    private static String readJsOrcss(String src) throws IOException {
        InputStream fis = null;
        ByteArrayOutputStream baos = null;
        try {
            baos = new ByteArrayOutputStream();
            fis = MarkdownUtils.class.getResourceAsStream(src);
            byte[] buffer = new byte[1024];

            int len;
            if (fis != null) {
                while ((len = fis.read(buffer)) != -1) {
                    baos.write(buffer, 0, len);
                }
            }

            String text = baos.toString();
            text = text.replaceAll("(\r\n|\r|\n|\n\r)", "");
            return text;
        } finally {
            closeio(fis);
            closeio(baos);
        }
    }

    /**
     * 转成驼峰式命名
     *
     * @param str /
     * @return /
     */
    private static String htmlConvert(String str) {
        return StringEscapeUtils.escapeHtml(str);
    }

    /**
     * 关闭流
     *
     * @param io /
     */
    private static void closeio(Closeable io) {
        if (io != null) {
            try {
                io.close();
            } catch (IOException var2) {
                io = null;
                var2.printStackTrace();
            }
        }
    }
}